﻿/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using EvaluationException = System.Qizx.Api.EvaluationException;
using QName = System.Qizx.Api.QName;
using QizxException = System.Qizx.Api.QizxException;
using CorePushBuilder = System.Qizx.Xdm.CorePushBuilder;
using IQName = System.Qizx.Xdm.IQName;
using EvalContext = System.Qizx.XQuery.EvalContext;
using ExprDisplay = System.Qizx.XQuery.ExprDisplay;
using Focus = System.Qizx.XQuery.Focus;
using ModuleContext = System.Qizx.XQuery.ModuleContext;
using XQType = System.Qizx.XQuery.XQType;
using XQValue = System.Qizx.XQuery.XQValue;
using ArraySequence = System.Qizx.XQuery.Dt.ArraySequence;
using SingleNode = System.Qizx.XQuery.Dt.SingleNode;
using System.Qizx.Xdm;
using System.Qizx.Api;
using System.Qizx.XQuery.Fn;
using System.Qizx.XQuery.Dt;

namespace System.Qizx.XQuery.Op {
    class FunctionItemCall : Expression {
        public Expression function;
        public Expression[] args = new Expression[0];

        public FunctionItemCall(Expression functionItem) {
            this.function = functionItem;
        }

        public void addArgument(Expression arg) {
            args = addExpr(args, arg);
        }

        public int getArgCount() {
            return args.Length;
        }

        public override Expression Child(int rank) {
            return rank == 0 ? function : (rank < args.Length) ? args[rank - 1] : null;
        }

        public void dump(ExprDisplay d) {
            d.header(this);
            d.child("function", function);
            d.children(args);
        }

        public override Expression StaticCheck(ModuleContext context, int flags) {
            function = context.staticCheck(function, 0);
            for (int a = 0; a < args.Length; a++)
                args[a] = context.staticCheck(args[a], 0);
            XQType ftype = function.getType();
            if (ftype is FunctionType) {
                Prototype fprot = ((FunctionType)ftype).getSignature();
                if (fprot != null && !fprot.accepts(args.Length))
                    // surely it is an error
                    context.error("XPTY0004", this, "invalid number of arguments");
                type = fprot.returnType;
            }
            return this;
        }

        public override XQValue eval(Focus focus, EvalContext context)
    {
        XQItem fun = function.evalAsItem(focus, context);
        if(!(fun is FunctionItem))
            context.badTypeForArg(XQType.FUNCTION, function, 0, "function item");
        
        FunctionItem funItem = (FunctionItem) fun;
        Prototype proto = funItem.prototype;
        
        return proto.invoke(args, this, funItem.lexicalContext, focus, context);
    }
    }
}